package net.xdclass.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author zhaowei
 * @Description TODO
 * @Remark 有问题直接联系我
 * @Version 1.0
 **/
public class ReflectTest {


    public static void main(String[] args) throws Exception {

        test8();
    }



    public static void test8() throws Exception {

        //获取类对象
        Class<User> userClass = User.class;

        //获取构造函数,并创建对象
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
        //确保有访问权限
        declaredConstructor.setAccessible(true);
        User user = declaredConstructor.newInstance();
        user.setName("老王");
        user.setAge(99);

        //获取指定的方法
        Method say = userClass.getDeclaredMethod("say", String.class);
        //保证方法可用
        say.setAccessible(true);


        //invoke调用,第一个参数是对象，第二个参数是入参
        Object returnValue = say.invoke(user, "大钊老师");
        System.out.println(returnValue);

        System.out.println("_____调用静态方法____");

        Method sleepMethod = userClass.getDeclaredMethod("sleep", String.class);
        //保证方法可用
        sleepMethod.setAccessible(true);
        //调用静态方法，不用获取类对象
        Object returnValue2 = sleepMethod.invoke(null, "冰冰");
        //方法没返回值，所以就null
        System.out.println(returnValue2);



    }

    public static void test7() throws Exception {

        //获取类对象
        Class<Product> productClass = Product.class;
        Constructor<Product> declaredConstructor = productClass.getDeclaredConstructor();
        //修改构造函数访问权限
        declaredConstructor.setAccessible(true);
        Product product = declaredConstructor.newInstance();
        System.out.println(product);

        //获取属性
        Field title = productClass.getDeclaredField("title");

        title.setAccessible(true);

        //设置指定对象的属性值
        title.set(product,"小滴云架构大课反射板块");
        System.out.println(product);


        Field price = productClass.getDeclaredField("price");
        price.setAccessible(true);
        price.set(product,9999);
        System.out.println(product);

    }



    public static void test6() throws Exception {
        //获取类对象
        Class<User> userClass = User.class;

        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        User user = declaredConstructor.newInstance();
        user.setName("冰冰");
        System.out.println(user.toString());

    }


    public static void test5() throws Exception {
        //获取类对象
        Class<User> userClass = User.class;

        //获取的public的属性，当前类和父类
        Field[] fields = userClass.getFields();
        for(Field field:fields){
            System.out.println("属性名="+field.getName()+",属性类型="+field.getType().getName()+"，修饰符="+field.getModifiers());
        }

        System.out.println("_______");

        //能获取当前类的全部属性，权限修复符不影响
        Field[] declaredFields = userClass.getDeclaredFields();
        for(Field field:declaredFields){
            System.out.println("属性名="+field.getName()+",属性类型="+field.getType().getName()+"，修饰符="+field.getModifiers());
        }


    }

    public static void test4() throws Exception {

        //获取类对象
        Class<User> userClass = User.class;
        //获取当前类和父类中声明的方法，需要是public类型
        Method[] methods = userClass.getMethods();
        for(Method method : methods){
            System.out.println("修饰符="+method.getModifiers()+",返回值="+method.getReturnType().getName()+",method="+method);
        }

        System.out.println("_________");
        //获取当前类的全部方法，不管修饰符
        Method[] declaredMethods = userClass.getDeclaredMethods();
        for(Method method : declaredMethods){
            System.out.println("修饰符="+method.getModifiers()+",返回值="+method.getReturnType().getName()+",method="+method);
        }


    }
    public static void test3() throws Exception {
        //获取类对象
        Class<User> clazz = User.class;

        //获取指定构造器
        Constructor constructor = clazz.getConstructor(int.class,String.class);

        //创建对象
        User user = (User) constructor.newInstance(21,"冰冰");
        System.out.println(user);

    }

    public static void  test2()throws Exception{

        Class<User> userClass = User.class;

        //获取空构造函数，并且创建对象
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
        //如果获取的是private类型的构造函数，则不能直接new对象
        User user = declaredConstructor.newInstance();

        user.setAge(111);
        user.setName("老王");

        System.out.println(user.toString());

    }

    public static void  test1() throws Exception {
        //通过类名获取
        Class<User> userClass1 = User.class;

        //通过对象获取
        User user = new User(1);
        Class<? extends User> userClass2 = user.getClass();

        //通过全限定名
        Class<?> userClass3  = Class.forName("net.xdclass.reflect.User");

        //通过类加载器
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        Class<?> userClass4 = classLoader.loadClass("net.xdclass.reflect.User");

        System.out.println(userClass1);
        System.out.println(userClass2);
        System.out.println(userClass3);
        System.out.println(userClass4);

        System.out.println("getName="+userClass1.getName());
        System.out.println("getSimpleName="+userClass1.getSimpleName());


        //根据参数，获取构造器，修饰符不影响
        Constructor<User> declaredConstructor = userClass1.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor.getName()+","+declaredConstructor.getParameterCount());


        System.out.println("----getDeclaredConstructors-----");
        //获取全部构造器，修饰符不影响
        Constructor<?>[] declaredConstructors = userClass1.getDeclaredConstructors();
        for(Constructor c:declaredConstructors){
            System.out.println(c.getName()+","+c.getParameterCount());
        }

        System.out.println("----getConstructors-----");
        Constructor<?>[] constructors = userClass1.getConstructors();
        for(Constructor c:constructors){
            System.out.println(c.getName()+","+c.getParameterCount());
        }

    }

}
